import axios from 'axios'
import { ElMessage } from 'element-plus'
import { indexStore } from '@/store'
import Encrypt from '@/utils/encrypt'
import { getToken, setToken, setRefreshToken, removeToken } from '@/utils/auth'
import type { AxiosResponse, AxiosRequestConfig, AxiosPromise } from 'axios'
import type { configType } from '@/api/type/index'

interface headerInter {
  'version': string,
  'Accept': string,
  'Content-Type': string,
  'x-ciot-platform': Date | string | number,
  'Authorization': string | null
  [props: string]: any;
}

const token = "Bearer uiap-omc-start::admin23::0::6981ec0e-91a8-4224-b272-4d0b309b45c4"

let store: any
setTimeout(() => {
  store = indexStore()
})
// create an axios instance

const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API
})

const errorBackLogin = () => {
  // removeToken()
  store.user.gwloginOut()
  // window.location.href = location.origin + '/passport/login'
}

const isTokenExpired = () => { // 验证当前token是否过期
  const expireTime = store.user.expires_time && Encrypt.decode(store.user.expires_time)
  if (expireTime) {
    const nowTime = parseInt(String(new Date().getTime() / 1000))
    const willExpired = (Number(expireTime) - nowTime) < 300// 如果小于5分钟重新获取token
    return willExpired
  }
  return false
}
// 是否正在刷新的标记 -- 防止重复发出刷新token接口--节流阀
let isRefreshing = false
// 失效后同时发送请求的容器 -- 缓存接口
let subscribers: any[] = []
// 刷新 token 后, 将缓存的接口重新请求一次
function onAccessTokenFetched(tokenType: string, newToken: string) {
  subscribers.forEach((callback) => {
    callback(tokenType, newToken)
  })
  // 清空缓存接口
  subscribers = []
}
// 添加缓存接口
function addSubscriber(callback: Function) {
  subscribers.push(callback)
}

// request interceptor
service.interceptors.request.use(
  (config: any) => {
    // // 若为生成环境 则根据不同接口进行不同host请求
    // let proBaseUrl=config.url.includes('/passport/') && import.meta.env.NODE_ENV === 'production'?import.meta.env.VITE_APP_PRO_BASE_API:import.meta.env.VITE_APP_BASE_API

    // config.baseURL=import.meta.env.NODE_ENV === 'development' ? '/api' : import.meta.env.VITE_APP_BASE_API

    // console.log(config.url)
    const header: Partial<headerInter> = {
      'version': 'v1',
      'Accept': 'application/json',
      // 'X-FRAME-OPTIONS': 'SAMEORIGIN',
      'Content-Type': 'application/json',
      'x-ciot-platform': new Date().getTime(),
      'Authorization': null
    }

    if (config.url.includes('/passport/login') && config.method === 'post') {
      header.Authorization = ''
    }

    if (isTokenExpired() && import.meta.env.VITE_APP_RUN_ENV != 'prod') { // 如果token快过期了
      if (!isRefreshing) { // 控制重复获取token
        isRefreshing = true
        const params = {
          url: '/api/passport/login/put',
          method: 'post',
          data: {
            refreshToken: store.user.refreshToken
          },
          async: false,
          headers: {
            'Authorization': token
          }
        }
        axios(params).then(res => {
          isRefreshing = false
          if (res.status === 200 && res.data.code === '2000000') {
            const data = res.data.data
            store.user.$patch(() => {
              store.user.token = data.tokenType + ' ' + data.accessToken
              store.user.refreshToken = data.refreshToken
              store.user.expires_time = data.expiresIn
            })
            setRefreshToken(data.refreshToken)
            setToken(data.tokenType + ' ' + data.accessToken, data.expiresIn)
            onAccessTokenFetched(data.tokenType, data.accessToken)
          } else {
            errorBackLogin()
            return
          }
        }).catch(() => {
          errorBackLogin()
          isRefreshing = false
          return
        })
      }
      // 将其他接口缓存起来 -- 这个Promise函数很关键
      const retryRequest = new Promise((resolve) => {
        // 这里是将其他接口缓存起来的关键, 返回Promise并且让其状态一直为等待状态,
        // 只有当token刷新成功后, 就会调用通过addSubscriber函数添加的缓存接口,
        // 此时, Promise的状态就会变成resolve
        addSubscriber((tokenType: string, newToken: string) => {
          // 表示用新的token去替换掉原来的token
          config.headers.Authorization = tokenType + ' ' + newToken
          // 替换掉url -- 因为baseURL会扩展请求url
          config.url = config.url

          // 返回重新封装的config, 就会将新配置去发送请求
          resolve(config)
        })
      })
      return retryRequest
    }
    header.Authorization = token
    config.headers = header

    // 修改请求前缀
    if (config.url.includes('/passport') && !config.url.includes('/omc')) {
      config.baseURL = '/gw/imc/api'
    }
    return config
  },
  error => {
    // do something with request error
    // console.log(error) // for debug
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const res = response.data

    if (res.code !== '2000000' && res.code) {
      let message = ''
      if (res.message && res.message.includes('errMessage') && typeof JSON.parse(res.message) === 'object') {
        message = JSON.parse(res.message).errMessage
      }
      const indexMessage = 'Unable to find instance for uiap'
      if (message.indexOf(indexMessage) > -1 || res.message.indexOf(indexMessage) > -1) {
        ElMessage({
          message: '服务升级中，请稍后再试',
          type: 'error',
          duration: 5 * 1000
        })
      } else {
        ElMessage({
          message: message || (res.message || '未知异常'),
          type: 'error',
          duration: 5 * 1000
        })
      }

      if (res.code === '4010001') {
        errorBackLogin()
      }

      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
    }
  },
  error => {
    const res = error.response
    // console.log(res)
    if (res.status === 401 || res.status === 424) {
      errorBackLogin()
    }
    let message = ''
    if (res.data.message && res.data.message.includes('errMessage') && typeof JSON.parse(res.data.message) === 'object') {
      message = JSON.parse(res.data.message).errMessage
    }
    const indexMessage = 'Unable to find instance for uiap'
    if (message.indexOf(indexMessage) > -1 || res.data.message.indexOf(indexMessage) > -1) {
      ElMessage({
        message: '服务升级中，请稍后再试',
        type: 'error',
        duration: 5 * 1000
      })
    } else {
      ElMessage({
        message: message || (res.data.message || '未知异常'),
        type: 'error',
        duration: 5 * 1000
      })
    }

    return Promise.reject(error)
  }
)

export default (url: string, method: string, params: any, config: configType = {}) => {
  // 负责发请求
  return service({
    url,
    method,
    [method.toLowerCase() === 'get' ? 'params' : 'data']: params
  }).then(res => {
    if (config.downLoad) {
      const contentDisposition = res.headers['content-disposition']
      let fileName = ''
      if (contentDisposition) {
        fileName = contentDisposition.replace(/.*filename=(.*)/, '$1')
      }
      fileName = decodeURI(fileName)
      const url = window.URL.createObjectURL(res.data)
      const link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      link.setAttribute('download', fileName)

      document.body.appendChild(link)
      link.click()
      URL.revokeObjectURL(link.href)
      document.body.removeChild(link)
      return { data: res.data }
    }
    return res
  }, err => {
    ElMessage.error(err.response.data.message || '登录失败')
    return err
  })
}
